//
// Created by xy on 2024/10/19.
//

#include "config.h"
#include "log.h"

#define INI_SIZE 128

char* parseINI(const char* key,const char* path){
  if (path == NULL){
    path = "config.ini";
  }
  FILE* filestream = open_filestream(path);
  if (filestream == NULL){
    ERROR_LOG("open %s failed",path);
    return NULL;
  }

  char line[INI_SIZE];
  char* value = NULL;
  while (fgets(line,INI_SIZE,filestream) != NULL){  // 逐行读取
    int value_start = 0;
    if ((value_start = isKey(key,line)) != -1){
      value = strdup(getValue(line,value_start));
      break;
    }
  }
  fclose(filestream);

  if (value == NULL){
    INFO_LOG("No value found for %s mapping",key);
  }

  trimWhitespace(value);
  return value;
}

// 修剪函数，去除字符串两端的空格
char* trimWhitespace(char* str) {
  // 去掉开头的空格
  while (isspace((unsigned char)*str)) str++;

  // 去掉结尾的空格
  char* end = str + strlen(str) - 1;
  while (end > str && isspace((unsigned char)*end)) end--;

  // 在结尾加上 '\0'
  *(end + 1) = '\0';
  return str;
}

FILE* open_filestream(const char* path){
  FILE* src = fopen(path, "r");
  if (!src) {
    DEBUG_LOG("fopen failed");
    return NULL;
  }
  return src;
}

int isKey(const char* key,const char* data){
  int key_end = 0;

  if (key[0] == '#' || key[0] == ' ') return -1;

  // 找到等号位置
  while (data[key_end] != '=' && data[key_end] != '\0') {
    key_end++;
  }

  // 如果已到达末尾，还没有找到，说明此数据本身也不合法
  if (data[key_end] == '\0') return -1;

  // 分离出 key
  char target[key_end + 1];
  strncpy(target,data,key_end);
  target[key_end] = '\0';

  // 比较 是否为目标 key
  if (strcmp(target, key) == 0) {
    return key_end + 1;
  } else {
    return -1;
  }
}

const char* getValue(char* data, int start) {
  int end = start;
  while (data[end] != '\0' && data[end] != '\n') {
    end++;
  }

  data[end] = '\0';
  return data + start;
}



/*
 * fgets注意点
 * 使用该函数时请注意，在读取 (n-1) 个字符前，并且读取到换行符时
 * fgets() 将会把换行符也存储进 str 中，同时缓冲区中不会留下换行符。
*/

/*
 * line 数组里面的内容会不会在下一次读取数据进来而有多余数据？
 * line 是一个固定大小的字符数组，每次通过 fgets 函数从文件中读取一行数据。
 * fgets 会自动处理换行符并在每次调用时将读取的数据放入 line 中。
 * 如果读取的行长度小于或等于 INI_SIZE - 1，则 fgets 会在 line 数组末尾自动添加一个空字符 '\0' 以表示字符串的结束。
 * 因此，line 数组中的内容会被新读取的数据覆盖。
*/

/*
 * strdup 函数的作用和注意点
 * 主要是拷贝字符串 s 的一个副本，由函数返回值返回，这个副本有自己的内存空间，和 s不相干
 * strdup函数复制一个字符串，使用完后要记得删除在函数中动态申请的内存，strdup函数的参数不能为NULL
 * 一旦为NULL，就会报段错误，因为该函数包括了strlen函数，而该函数参数不能是NULL
 * 由于内部本质是 malloc，返回值若不再使用，需要 free
*/
